#ifndef __CMD_UART_H
#define __CMD_UART_H

#include "../conn/message.h"
#include "../conn/proto.h"
#include "../rtos/event_flags.h"
#include "../rtos/message_queue.h"
#include "../utils/byte_view.h"


namespace driver {

class CmdUart : private utils::NoCopyable {

public:
    static constexpr uint32_t RECV_BUF_SIZE = 320;
    static constexpr uint32_t WRITE_BUF_SIZE = 96;

    static constexpr uint32_t FLAG_DMA_TC = 0x01;

    void init();

    template <typename... Ts>
    void write(uint8_t action, const Ts&... ts) {
        m_flags.wait_any_flags(FLAG_DMA_TC);
        uint8_t n = conn::proto::make(m_write_buf, action, ts...);
        write_by_dma(m_write_buf, n);
    }

    void on_recv_idle();
    void on_dma_tc() { m_flags.set_flags(FLAG_DMA_TC); }
    osStatus_t poll(utils::ByteView &bw, uint32_t timeout = osWaitForever) {
        return m_mq.poll(bw, timeout);
    }
private:
    static void write_by_dma(const void *buf, uint16_t len);
    uint8_t m_recv_buf[RECV_BUF_SIZE];
    uint8_t m_write_buf[WRITE_BUF_SIZE];
    volatile uint32_t m_recv_index = 0;
    rtos::MessageQueue<utils::ByteView, 5> m_mq;
    rtos::EventFlags m_flags;
};

extern CmdUart cmdUart;

} // namespace driver

#endif
